package com.glela.controller;

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import com.alibaba.fastjson.JSONObject;
import com.glela.cache.redis.RedisKeys;
import com.glela.cache.redis.RedisUtil;
import com.glela.common.util.JsonUtil;
import com.glela.platform.constant.ErrorEnum;
import com.glela.platform.model.response.ResponseBaseModel;
import com.glela.platform.model.response.ResponseResultModel;

abstract class BaseController {
	private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());

	/** 默认缓存秒 */
	private static final int					SECONDS		= 60 * 10 * 1;
	private static final Map<String, String>	_cache_key	= new LinkedHashMap<>();
	@Autowired
	protected RedisUtil							redisUtil;

	/** redis工具类 */
	protected RedisUtil getRedisUtil() {
		return redisUtil;
	}

	/**
	 * <dl>
	 * <dt>获取缓存键值</dt>
	 * </dl>
	 * @param key多参数定义的组合键
	 * @return String
	 * @author zls
	 * @date 2017年10月27日 下午5:40:04
	 */
	protected String getTempCacheKey(Object... key) {
		if (ArrayUtils.isEmpty(key)) {
			return StringUtils.EMPTY;
		} else {
			if (key.length > 1) {
				StringBuilder stringBuilder = new StringBuilder();
				for (int i = 0; i < key.length;) {
					stringBuilder.append(key[i]);
					if (++i < key.length) {
						stringBuilder.append(":");
					}
				}
				return stringBuilder.toString();
			} else {
				return String.valueOf(key[0]);
			}
		}
	}

	/**
	 * <dl>
	 * <dt>读取缓存结果</dt>
	 * </dl>
	 * @return String
	 * @author zls
	 * @date 2017年10月27日 下午5:23:06
	 */
	protected String queryCacheResult() {
		return _redisGet(_get_cahe_key());
	}

	/**
	 * <dl>
	 * <dt>获取缓存结果</dt>
	 * <dd>需判断是否为空，为空从数据库读取</dd>
	 * </dl>
	 * @param key 缓存键
	 * @return String
	 * @author zls
	 * @date 2017年10月27日 下午5:42:37
	 */
	protected String queryCacheResult(String key) {
		return _redisGet(_get_cahe_key(key));
	}

	protected String queryCacheResult(Object key) {
		return _redisGet(_get_cahe_key(String.valueOf(key)));
	}

	protected String toResultModelJSON(Object obj) {
		return toJSONString(new ResponseResultModel<>(obj));
	}

	protected String toResultModelJSON(ErrorEnum errorEnum,Object obj) {
		return toJSONString(new ResponseResultModel<>(errorEnum,obj));
	}

	protected String toResultModelJSONNew(Object obj) {
		return toJSONStringNew(new ResponseResultModel<>(obj));
	}

	protected ResponseResultModel<T> toResultModel(T obj) {
		return new ResponseResultModel<>(obj);
	}

	protected ResponseBaseModel toErrorModel(ErrorEnum errorEnum) {
		return new ResponseBaseModel(errorEnum);
	}

	protected String toErrorModelJSON(ErrorEnum errorEnum) {
		return toJSONString(new ResponseBaseModel(errorEnum));
	}

	/**
	 * <dl>
	 * <dt>缓存结果</dt>
	 * </dl>
	 * @param value 结果
	 * @return String
	 * @author zls
	 * @date 2017年10月27日 下午5:20:55
	 */
	protected String toCacheResult(String value) {
		return _redisSetex(_get_cahe_key(), SECONDS, value);
	}

	/**
	 * <dl>
	 * <dt>缓存结果</dt>
	 * </dl>
	 * @param value 结果
	 * @param seconds 缓存时长（秒）
	 * @return String
	 * @author zls
	 * @date 2017年10月27日 下午5:21:27
	 */
	protected String toCacheResult(String value, int seconds) {
		return _redisSetex(_get_cahe_key(), seconds, value);
	}

	/**
	 * <dl>
	 * <dt>缓存结果</dt>
	 * </dl>
	 * @param key 键
	 * @param value 结果
	 * @return String
	 * @author zls
	 * @date 2017年10月27日 下午5:21:53
	 */
	protected String toCacheResult(String key, String value) {
		return _redisSetex(_get_cahe_key(key), SECONDS, value);
	}

	protected String toCacheResult(Object key, String value) {
		return _redisSetex(_get_cahe_key(String.valueOf(key)), SECONDS, value);
	}

	/**
	 * <dl>
	 * <dt>缓存结果</dt>
	 * </dl>
	 * @param key 键
	 * @param value 结果
	 * @param seconds 有效时长（秒）
	 * @return String
	 * @author zls
	 * @date 2017年10月27日 下午5:22:31
	 */
	protected String toCacheResult(String key, String value, int seconds) {
		return _redisSetex(_get_cahe_key(key), seconds, value);
	}

	/**
	 * <dl>
	 * <dt>封装响应结果实体类</dt>
	 * </dl>
	 * @param rslt 结果
	 * @return ResponseEntity<String>
	 * @author zls
	 * @date 2017年10月27日 下午6:01:19
	 */
	protected ResponseEntity<?> toRespEntity(Object rslt) {
		return new ResponseEntity<>(rslt, HttpStatus.OK);
	}

	/**
	 * <dl>
	 * <dt>封装响应结果实体类</dt>
	 * </dl>
	 * @param rslt 结果
	 * @param httpStatus HTTP status codes
	 * @return ResponseEntity<?>
	 * @author zls
	 * @date 2017年10月28日 上午10:34:55
	 */
	protected ResponseEntity<?> toRespEntity(Object rslt, HttpStatus httpStatus) {
		return new ResponseEntity<>(rslt, httpStatus);
	}

	/**
	 * <dl>
	 * <dt>对象转json字符串</dt>
	 * </dl>
	 * @param obj
	 * @return String
	 * @author zls
	 * @date 2017年10月28日 上午10:05:05
	 */
	protected String toJSONString(Object obj) {
		try {
			return JsonUtil.toJson(obj);
		} catch (Exception e) {
			getLOGGER().error("controller公用缓存转json失败：{}", e.getMessage(), e);
			return null;
		}
	}

	protected String toJSONStringNew(Object obj) {
		try {
			//			return JsonUtil.toJson(obj);
			return JSONObject.toJSONString(obj);
		} catch (Exception e) {
			getLOGGER().error("controller公用缓存转json失败：{}", e.getMessage(), e);
			return null;
		}
	}

	protected Logger getLOGGER() {
		return LOGGER;
	}

	private String _redisSetex(String key, int seconds, String value) {
		try {
			getRedisUtil().setex(key, seconds, value);
		} catch (Exception e) {
			getLOGGER().warn("redis异常{}", e.getMessage());
		}
		return value;
	}

	private String _redisGet(String key) {
		try {
			return getRedisUtil().get(key);
		} catch (Exception e) {
			getLOGGER().warn("redis异常{}", e.getMessage());
			return null;
		}
	}

	private String _get_cahe_key() {
		String className = getClassNameKey();
		if (StringUtils.isEmpty(_cache_key.get(className))) {
			_cache_key.put(className, StringUtils.replace(className, ".", ":"));
		}
		return _cache_key.get(className);
	}

	private String _get_cahe_key(String key) {
		String className = getClassNameKey();
		if (StringUtils.isEmpty(key)) {
			throw new NullPointerException("缓存键为空");
		} else {
			className += ":" + key;
		}
		if (StringUtils.isEmpty(_cache_key.get(className))) {
			_cache_key.put(className, StringUtils.replace(className, ".", ":"));
		}
		return _cache_key.get(className);
	}

	public String _public_get_cahe_key(String key) {
		String className = getClassNameKey();
		if (StringUtils.isEmpty(key)) {
			throw new NullPointerException("缓存键为空");
		} else {
			className += ":" + key;
		}
		if (StringUtils.isEmpty(_cache_key.get(className))) {
			_cache_key.put(className, StringUtils.replace(className, ".", ":"));
		}
		return _cache_key.get(className);
	}

	private String getClassNameKey() {
		StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
		String className = stackTrace[4].getClassName() + "." + stackTrace[4].getMethodName();
		stackTrace = null;
		className = RedisKeys.TEMP_ + className;
		return className;
	}

}
